package com.scs.application.modules.dept.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.consts.SerialKeys;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.flow.FlowContext;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.BeanUtils;
import com.scs.application.core.utils.DateUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.base.service.DeptService;
import com.scs.application.modules.dept.dto.BudgetDTO;
import com.scs.application.modules.dept.entity.Budget;
import com.scs.application.modules.dept.entity.BudgetItem;
import com.scs.application.modules.dept.entity.BudgetMatr;
import com.scs.application.modules.dept.mapper.BudgetMapper;
import com.scs.application.modules.dept.service.BudgetItemService;
import com.scs.application.modules.dept.service.BudgetMatrService;
import com.scs.application.modules.dept.service.BudgetService;
import com.scs.application.modules.dept.util.UtilBudget;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 */
@Service
public class BudgetServiceImpl extends BaseServiceImpl<BudgetMapper, Budget> implements BudgetService {

    @Autowired
    private BudgetItemService budgetItemService;

    @Autowired
    private DeptService deptService;

    @Autowired
    private BudgetMatrService budgetMatrService;
    /**
     * 获取当前时间对应统计周期
     * @return
     */
    @Override
    @Deprecated
    public Budget getCurrentBudget() {
        Date dateNow = Calendar.getInstance().getTime(); //默认

        List<Budget> budgetList = super.list(new QueryWrapper<Budget>().eq("flow_status", GlobalConsts.FLOW_PASS_VALUE).orderByDesc("period_year"));

        for(int i = 0 ; i < budgetList.size(); i++) {
            if(budgetList.get(i).getStartDate().before(dateNow) && budgetList.get(i).getEndDate().after(dateNow)) {
                return budgetList.get(i);
            }
        }
        return null; //没有合适的统计年份

    }

    @Override
    public boolean saveOrUpdate(Budget entity) {
        QueryWrapper queryWrapperCheck = Wrappers.<Budget>query().eq("period_year",entity.getPeriodYear()).eq("period_month",entity.getPeriodMonth());
        //非全院限制时，筛选填报科室
        String msgPre ="全院";
        if (entity.getFlagHospital()) {//全院限制
            queryWrapperCheck.eq("flag_hospital","1");
        }else  { //非全院限制，查询对应科室的
            queryWrapperCheck.ne("flag_hospital","1");
            queryWrapperCheck.eq("dept_id",entity.getDeptId());
            msgPre ="科室";
        }
        //业务科室校验
//        CommonService.checkDept(entity.getDeptId());

        Budget budgetDb = this.getOne(queryWrapperCheck);
        if (budgetDb!=null && !budgetDb.getId().equals(entity.getId())) throw new BusinessException("%s %s"+msgPre+"预算已存在(单号：%s)，请调整年月或者删除该预算",entity.getPeriodYearMonth(),entity.getDeptName(),budgetDb.getBusKey());

        if (StringUtils.isBlank(entity.getBusKey())) {
            entity.setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.DEPT_BUDGET_KEY));
        }

        return super.saveOrUpdate(entity);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    protected void afterHandleFlowChange(FlowContext flowContext, Budget newEntity) {
        super.afterHandleFlowChange(flowContext, newEntity);

        boolean endNode = flowContext.isEndNode();
        if (!endNode) {
            return;
        }

        List<BudgetItem> budgetLastList = budgetItemService.list(new QueryWrapper<BudgetItem>()
                .eq("budget_id", newEntity.getId()) );
        //更新限制耗材数量
        if (budgetLastList != null && budgetLastList.size() > 0) {
            boolean have =false;
            budgetLastList.stream().forEach(budgetItem -> {
                double budgetMatrCount = budgetMatrService.count(new QueryWrapper<BudgetMatr>().eq("budget_item_id",budgetItem.getId()));
                budgetItem.setQtyMatr(budgetMatrCount);
                budgetItemService.updateById(budgetItem);
            });
        }
    }


    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        // applyItemMapper.delete(Wrappers.<ApplyItem>query().in("apply_id", idList));

        for (Serializable id : idList) {
            List<BudgetItem> budgetLastList = budgetItemService.list(new QueryWrapper<BudgetItem>()
                    .eq("budget_id", id) );
            if (budgetLastList != null && budgetLastList.size() > 0) {
                List<String> itemIdList = budgetLastList.stream().map(BudgetItem::getId).collect(Collectors.toList());
                budgetItemService.removeCascadeByIds(itemIdList);
            }
        }
        return super.removeCascadeByIds(idList);
    }

    @Override
    public boolean removeCascadeById(Serializable id) {
        this.removeCascadeByIds(Arrays.asList(id));
        return true;
    }

    @Override
    protected void beforeHandleFlowChange(FlowContext flowContext, Budget newEntity) {
        List<BudgetItem> budgetLastList = budgetItemService.list(new QueryWrapper<BudgetItem>()
                .eq("budget_id", newEntity.getId()) );
        String buttonKey = flowContext.getButtonKey();
        if ((buttonKey.equals("submit") || flowContext.isEndNode() ) && ( budgetLastList == null || budgetLastList.size() <1)) {
            throw new BusinessException("该预算单没有任何明细，请添加后再提交");
        }
        super.beforeHandleFlowChange(flowContext, newEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Budget copy(String id) {
        if (StringUtils.isBlank(id)) throw new BusinessException("缺少参数【id】");
        Budget budget =baseMapper.selectById(id);
        if (budget == null) throw new BusinessException("所操作的单子已被删除，请刷新重试");
        budget.setId(null).setGmtCreate(LocalDateTime.now());
        budget.setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.DEPT_BUDGET_KEY));
        budget.setFlowStatus("start").setFlowModified(null).setFlowModifier(null);

        //日期字段
        Date dateNow = DateUtils.now();
        LocalDateTime localDateTime = DateUtils.dateToLocalDateTime(dateNow);
        Date dateBegin = DateUtils.getFirstDayOfMonth(dateNow);
        Date dateEnd = DateUtils.getLastDayOfMonth(dateNow);

        String dateNowYmd = DateUtils.format(dateNow,"yyyy-MM-dd");
        String[] ymdArr= dateNowYmd.split("-");
        budget.setBusDate(dateNow).setPeriodYearMonth("").setGmtCreate(localDateTime);

        //年-月
        budget.setPeriodYearMonth(ymdArr[0]+"-"+ymdArr[1]);
        //年、月
        budget.setPeriodYear(Integer.parseInt(ymdArr[0])).setPeriodMonth(Integer.parseInt(ymdArr[1]));
        //月起止日期
        budget.setStartDate(dateBegin).setEndDate(dateEnd);

        //当月消耗额
        budget.setAmountUseMonth(0d).setQtyUseMonth(0d).setLastMonthAmount(0d).setLastMonthQty(0d).setLastYearAmount(0d).setLastYearQty(0d);

        BudgetDTO budgetDTO = UtilBudget.getQtyAmount(Integer.parseInt(ymdArr[0]),Integer.parseInt(ymdArr[1]), budget.getDeptId(),dateBegin,dateEnd,budget.getFlagHospital());
        if (budgetDTO != null) BeanUtils.copyProperties(budgetDTO,budget);
        this.saveOrUpdate(budget);

        //预算明细
        List<BudgetItem> budgetLastList = budgetItemService.list(new QueryWrapper<BudgetItem>()
                .eq("budget_id", id) );
        if (budgetLastList != null && budgetLastList.size() > 0) {
            budgetLastList.stream().forEach(budgetItem -> {
                String itemIdOld = budgetItem.getId();
                budgetItem.setBudgetId(budget.getId()).setId(null);
                budgetItemService.save(budgetItem);

                //耗材明细
                List<BudgetMatr> budgetMatrList = budgetMatrService.list(new QueryWrapper<BudgetMatr>().eq("budget_item_id",itemIdOld));
                if (budgetMatrList != null && budgetMatrList.size() > 0) {
                    budgetMatrList.stream().forEach(budgetMatr -> {
                        budgetMatr.setBudgetId(budget.getId()).setBudgetItemId(budgetItem.getId()).setId(null);
                        budgetMatrService.save(budgetMatr);
                    });
                }
            });
        }
        return budget;
    }
}
